/*
 * ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
 * Without permission, no one has the right to obtain, disclose or use this software in any way.
 */
package com.ecarx.systemui.plugin.ui.dialog

import android.annotation.SuppressLint
import android.car.VehicleAreaSeat
import android.car.VehicleUnit
import android.car.hardware.CarPropertyValue
import android.car.hardware.property.CarPropertyManager
import android.content.Context
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.SeekBar
import android.widget.TextView
import com.ecarx.systemui.plugin.AppConstants
import com.ecarx.systemui.plugin.R
import com.ecarx.systemui.plugin.controller.hvac.HvacTempController
import com.ecarx.systemui.plugin.controller.hvac.TempSignalController
import com.ecarx.systemui.plugin.model.listener.NoDoubleClickListener
import com.ecarx.systemui.plugin.ui.dialog.base.AutoCloseDialog
import com.ecarx.systemui.plugin.ui.dialog.base.DialogManager
import com.ecarx.systemui.plugin.utils.BitmapUtils
import com.ecarx.systemui.plugin.utils.ClimateTempUtils
import com.ecarx.systemui.plugin.utils.LogUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class PassengerTempDialog(private val location: IntArray, context: Context) :
    AutoCloseDialog(context, 0) {
    private var llRoot: LinearLayout? = null
    private var tvTemp: TextView? = null
    private var mTempSeekBar: SeekBar? = null
    private var viewLine: View? = null
    private var flDual: LinearLayout? = null
    private var ivSync: ImageView? = null
    private var tvSync: TextView? = null

    private var tempUnit = VehicleUnit.CELSIUS

    private val tempController: HvacTempController = HvacTempController.getInstance()
    private val mArea = VehicleAreaSeat.SEAT_ROW_1_RIGHT

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setCancelable(true)
        setCanceledOnTouchOutside(true)
        setContentView(R.layout.dialog_passenger_temp)
        initView()
        initConfig()
    }

    private fun initView() {
        llRoot = findViewById(R.id.ll_root)
        tvTemp = findViewById(R.id.tv_temp)
        mTempSeekBar = findViewById(R.id.sb_temp)
        with(mTempSeekBar) { this?.setMax(ClimateTempUtils.getMaxProgress()) }
        viewLine = findViewById(R.id.view_line)
        flDual = findViewById(R.id.fl_dual_view)
        ivSync = findViewById(R.id.iv_sync)
        tvSync = findViewById(R.id.tv_sync)

        registerListener()
        refreshView()
    }

    private fun refreshView() {
        CoroutineScope(Dispatchers.IO).launch {
            val isPowerOn = tempController.isPowerOn()
            if (!isPowerOn) {
                LogUtils.d(TAG, "setPowerOn true")
                tempController.setPowerOn(true)
            }

            val currentTemp = tempController.getCurrentTemp(mArea)
            val syncSupport = tempController.isTempSyncAvailable();
            val isSync = tempController.isTempSync();
            if (tempController.isTempUnitAvailable()) {
                tempUnit = tempController.getTempUnit()
            }
            withContext(Dispatchers.Main) {
                updateAgainShow(currentTemp, syncSupport, isSync, tempUnit);
            }
        }

    }

    private fun setTemp(temp: Float, reason: String) {
        LogUtils.d(TAG, "setTemp:$temp , for $reason")
        CoroutineScope(Dispatchers.IO).launch {
            tempController.setTemp(temp, mArea)
        }
    }

    private fun setTempSync(reason: String) {

        CoroutineScope(Dispatchers.IO).launch {
            val tempSync = !tempController.isTempSync()
            LogUtils.d(TAG, "setTempSync:$tempSync , for $reason")
            tempController.setTempSync(tempSync)
        }
    }


    private fun registerListener() {
        with(mTempSeekBar) {
            this?.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
                override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                    if (fromUser) {
                        LogUtils.d(TAG, "onProgressChanged:$progress")
                        val tempValue: Float = ClimateTempUtils.getTempByProgress(
                            tempUnit == VehicleUnit.CELSIUS,
                            progress
                        )
                        updateTempText(tempValue, tempUnit)
                        setTemp(tempValue, "seekbar onProgressChanged")
                    }
                }

                override fun onStartTrackingTouch(seekBar: SeekBar) {
                    cancelTimingClose()
                }

                override fun onStopTrackingTouch(seekBar: SeekBar) {
                    startTimingClose()
                    val progress = seekBar.progress
                    LogUtils.d(TAG, "onStopTrackingTouch:$progress")
                    val tempValue: Float = ClimateTempUtils.getTempByProgress(
                        tempUnit == VehicleUnit.CELSIUS,
                        progress
                    )
                    updateTempText(tempValue, tempUnit)
                    setTemp(tempValue, "seekbar stop tracking")
                }
            })
        }
        with(flDual) {
            this?.setOnClickListener(object : NoDoubleClickListener() {
                override fun onNoDoubleClick(view: View) {
                    startTimingClose()
                    setTempSync(" click temp dialog ")
                    refreshView()
                }
            })
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun initConfig() {
        val window = window
        if (window != null) {
            val params = window.attributes
            params.width = WindowManager.LayoutParams.WRAP_CONTENT
            params.height = WindowManager.LayoutParams.WRAP_CONTENT
            params.type = AppConstants.PLUGIN_DIALOG_TYPE
            params.gravity = Gravity.START or Gravity.TOP
            params.dimAmount = 0f
            params.x = location[0] - 1118/3
            params.y = location[1] - 176
            window.attributes = params
        }
    }

    override fun delayedDismiss() {
        dismiss()
    }

    private val tempCallback = object : CarPropertyManager.CarPropertyEventCallback {
        override fun onChangeEvent(value: CarPropertyValue<*>?) {
            LogUtils.d(TAG, "tempCallback value:$value")
            refreshView()
        }

        override fun onErrorEvent(p0: Int, p1: Int) {

        }

    }

    private val tempSyncCallback = object : CarPropertyManager.CarPropertyEventCallback {
        override fun onChangeEvent(value: CarPropertyValue<*>?) {
            LogUtils.d(TAG, "tempSyncCallback value:$value")
            refreshView()
        }

        override fun onErrorEvent(p0: Int, p1: Int) {

        }

    }

    private val powerOnCallback = object : CarPropertyManager.CarPropertyEventCallback {
        override fun onChangeEvent(value: CarPropertyValue<*>?) {
            LogUtils.d(TAG, "powerOnCallback value:$value")
            refreshView()
        }

        override fun onErrorEvent(p0: Int, p1: Int) {

        }
    }

    override fun show() {
        super.show()

        CoroutineScope(Dispatchers.IO).launch {
            tempController.registerPowerOnCallback(powerOnCallback)
            tempController.registerTempCallback(tempCallback)
            tempController.registerTempSyncCallback(tempSyncCallback)
        }

    }

    override fun dismiss() {
        llRoot?.startAnimation(outAnimation)
        llRoot?.postDelayed({
            super.dismiss()
            DialogManager.getDialogManager().cleanPassengerTempDialog()
        }, 150)

        CoroutineScope(Dispatchers.IO).launch {
            tempController.unRegisterPowerOnCallback(powerOnCallback)
            tempController.unRegisterTempCallback(tempCallback)
            tempController.unRegisterTempSyncCallback(tempSyncCallback)
        }
    }

    fun updateAgainShow(
        driverTempCurrentValue: Float,
        isSupportSync: Boolean,
        isSync: Boolean,
        tempUnit: Int
    ) {
        startTimingClose()
        updateTempAndSyncIsShow(driverTempCurrentValue, isSupportSync, isSync, tempUnit)
    }

    private fun updateTempAndSyncIsShow(
        driverTempValue: Float,
        isSupportSync: Boolean,
        isSync: Boolean,
        tempUnit: Int
    ) {
        this.tempUnit = tempUnit
        if (isSupportSync) {
            updateSyncIcon(isSync)
        } else {
            flDual?.visibility = View.GONE
            viewLine?.visibility = View.GONE
        }
        updateTempText(driverTempValue, tempUnit)
        updateProgress(driverTempValue, tempUnit)
    }

    private fun updateProgress(driverTempValue: Float, tempUnit: Int) {
        val progress = tempValueToProgress(driverTempValue, tempUnit)
        LogUtils.d(TAG, "updateProgress: $driverTempValue   tempUnit: $tempUnit")
        mTempSeekBar!!.progress = progress
    }

    private fun tempValueToProgress(driverTempValue: Float, tempUnit: Int): Int {
        return ClimateTempUtils.getProgressByTemp(VehicleUnit.CELSIUS == tempUnit, driverTempValue)
    }

    private fun updateTempText(value: Float?, tempUnit: Int) {
        if (value == null) {
            return
        }
        val MIN_TEMP: Float
        val MAX_TEMP: Float
        if (VehicleUnit.CELSIUS == tempUnit) {
            MIN_TEMP = TempSignalController.MIN_TEMP_C
            MAX_TEMP = TempSignalController.MAX_TEMP_C
        } else {
            MIN_TEMP = TempSignalController.MIN_TEMP_F
            MAX_TEMP = TempSignalController.MAX_TEMP_F
        }
        if (value <= MIN_TEMP) {
            tvTemp!!.setText(R.string.temp_lo)
        } else if (value >= MAX_TEMP) {
            tvTemp!!.setText(R.string.temp_hi)
        } else {
            tvTemp!!.text = value.toString()
        }
    }

    fun updateSyncIcon(isSync: Boolean) {
        LogUtils.d(TAG, "updateSyncIcon:$isSync")
        flDual?.visibility = View.VISIBLE
        viewLine?.visibility = View.VISIBLE
        if (isSync) {
            tvSync?.text = context.getString(R.string.sync)
            ivSync?.setImageBitmap(BitmapUtils.decodeRes(context, R.drawable.ic_nav_hvac_sync))
        } else {
            tvSync?.text = context.getString(R.string.un_sync)
            ivSync?.setImageBitmap(BitmapUtils.decodeRes(context, R.drawable.ic_nav_hvac_unsync))
        }
    }

    companion object {
        private const val TAG = "PassengerTempDialog"
    }
}